package cn.edu.gzgs.service;

import com.wf.captcha.SpecCaptcha;
import com.wf.captcha.base.Captcha;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class CaptchaService {

    private final StringRedisTemplate redisTemplate;
    private static final String CAPTCHA_KEY_PREFIX = "captcha:";

    // 从配置文件注入
    @Value("${application.captcha.expiration-minutes:3}") // 默认3分钟
    private long captchaExpirationMinutes;

    @Value("${application.captcha.length:5}") // 默认长度5
    private int captchaLength;

    @Value("${application.captcha.width:130}") // 默认宽度130
    private int captchaWidth;

    @Value("${application.captcha.height:48}") // 默认高度48
    private int captchaHeight;

    @Value("${application.captcha.char-type:DEFAULT}") // 默认类型DEFAULT (字母数字混合)
    private String captchaCharType; // 可配置为 TYPE_DEFAULT, TYPE_ONLY_NUMBER, TYPE_ONLY_CHAR, TYPE_ONLY_UPPER, TYPE_ONLY_LOWER

    @Autowired
    public CaptchaService(StringRedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    /**
     * 生成验证码图片并存储到Redis
     * @return 返回一个包含验证码唯一ID和Base64编码图片的CaptchaResponse对象
     */
    public CaptchaResponse generateCaptcha() {
        SpecCaptcha specCaptcha = new SpecCaptcha(captchaWidth, captchaHeight, captchaLength);
        
        // 设置验证码字符类型
        switch (captchaCharType.toUpperCase()) {
            case "TYPE_ONLY_NUMBER":
                specCaptcha.setCharType(Captcha.TYPE_ONLY_NUMBER);
                break;
            case "TYPE_ONLY_CHAR":
                specCaptcha.setCharType(Captcha.TYPE_ONLY_CHAR);
                break;
            case "TYPE_ONLY_UPPER":
                specCaptcha.setCharType(Captcha.TYPE_ONLY_UPPER);
                break;
            case "TYPE_ONLY_LOWER":
                specCaptcha.setCharType(Captcha.TYPE_ONLY_LOWER);
                break;
            default:
                specCaptcha.setCharType(Captcha.TYPE_DEFAULT);
        }
        
        String code = specCaptcha.text().toLowerCase();
        String imageBase64 = specCaptcha.toBase64();
        String captchaId = UUID.randomUUID().toString().replace("-", "");

        String redisKey = CAPTCHA_KEY_PREFIX + captchaId;
        try {
            redisTemplate.opsForValue().set(redisKey, code, captchaExpirationMinutes, TimeUnit.MINUTES);
            log.info("验证码已生成并存入Redis: captchaId={}, code={}, expiration={}min", captchaId, code, captchaExpirationMinutes);
        } catch (Exception e) {
            log.error("存储验证码到Redis失败: captchaId={}, code={}", captchaId, code, e);
            throw new RuntimeException("生成验证码失败，请稍后重试");
        }
        return new CaptchaResponse(captchaId, imageBase64);
    }

    /**
     * 校验验证码
     * @param captchaId 验证码唯一ID
     * @param userInputCode 用户输入的验证码
     * @return true 如果验证码正确，false 否则
     */
    public boolean validateCaptcha(String captchaId, String userInputCode) {
        if (!StringUtils.hasText(captchaId) || !StringUtils.hasText(userInputCode)) {
            return false;
        }
        String redisKey = CAPTCHA_KEY_PREFIX + captchaId;
        String storedCode = redisTemplate.opsForValue().get(redisKey);

        if (storedCode == null) {
            log.warn("验证码校验失败或已过期: captchaId={}", captchaId);
            return false; // 验证码不存在或已过期
        }

        boolean isValid = storedCode.equalsIgnoreCase(userInputCode.trim());
        if (isValid) {
            redisTemplate.delete(redisKey); // 验证成功后立即删除，防止重复使用
            log.info("验证码校验成功: captchaId={}", captchaId);
        } else {
            log.warn("验证码校验失败: captchaId={}, 用户输入='{}', 期望='{}'", captchaId, userInputCode, storedCode);
        }
        return isValid;
    }

    // 内部类用于封装验证码响应
    public static class CaptchaResponse {
        private String captchaId;
        private String imageBase64;

        public CaptchaResponse(String captchaId, String imageBase64) {
            this.captchaId = captchaId;
            this.imageBase64 = imageBase64;
        }

        public String getCaptchaId() {
            return captchaId;
        }

        public String getImageBase64() {
            return imageBase64;
        }
    }
} 